package com.hailiao.beidou.message.ui.page.connect

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.clj.fastble.data.BleDevice
import com.d10ng.app.managers.PermissionManager
import com.d10ng.app.status.isLocationEnabled
import com.d10ng.compose.model.UiViewModelManager
import com.hailiao.beidou.comm.bluetooth.BLEHub
import com.hailiao.beidou.comm.bluetooth.constant.BLEStatus
import com.hailiao.beidou.comm.bluetooth.data.NotifySettingInfo
import com.hailiao.beidou.message.bd.Beidou
import com.hailiao.beidou.message.bd.ble.BLEDeviceManager
import com.hailiao.beidou.message.bd.ble.IBLEDevice
import com.hailiao.beidou.message.data.setting.SettingRepository
import com.hailiao.beidou.message.utils.back
import com.hailiao.beidou.message.utils.bluetoothPermissionArray
import com.hailiao.beidou.message.utils.locationPermissionArray
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.launch

/**
 * 蓝牙连接界面
 * @Author d10ng
 * @Date 2024/3/5 13:50
 */
data class BLEDeviceData(
    // 信息
    val info: BleDevice,
    // 名称
    val name: String,
    // 地址
    val address: String,
    // 设备类型
    val type: IBLEDevice?,
    // 是否已适配
    val isAdapted: Boolean
)

class BLEConnectScreenViewModel: ViewModel() {

    // 蓝牙设备列表
    @OptIn(ExperimentalCoroutinesApi::class)
    val devicesFlow = BLEHub.scanDeviceListFlow.mapLatest { list ->
        list.filter { d -> d.name.isNullOrEmpty().not() }.map { b ->
            val name = b.name!!
            val type = BLEDeviceManager.getDevice(name)
            BLEDeviceData(
                info = b,
                name = name,
                address = b.mac,
                type = type,
                isAdapted = type != null
            )
        }.sortedByDescending { it.isAdapted }
    }

    // 是否正在扫描
    val isScanningFlow = BLEHub.isScanningFlow

    init {
        viewModelScope.launch {
            if (PermissionManager.request(locationPermissionArray + bluetoothPermissionArray)) {
                onRefresh()
            }
        }
    }

    /**
     * 下拉刷新
     */
    fun onRefresh() {
        // 检查蓝牙开关状态
        if (BLEHub.statusFlow.value == BLEStatus.DISABLE) {
            BLEHub.enableBluetooth()
            UiViewModelManager.showErrorNotify("蓝牙未打开！")
            return
        }
        // 检查定位权限
        if (PermissionManager.has(locationPermissionArray).not()) {
            UiViewModelManager.showErrorNotify("缺少定位权限，无法进行蓝牙扫描！")
            return
        }
        // 检查位置信息开关
        if (isLocationEnabled().not()) {
            UiViewModelManager.showErrorNotify("位置信息未打开，无法进行蓝牙扫描！")
            return
        }
        // 检查蓝牙扫描权限
        if (PermissionManager.has(bluetoothPermissionArray).not()) {
            UiViewModelManager.showErrorNotify("缺少蓝牙扫描权限，无法进行蓝牙扫描！")
            return
        }
        viewModelScope.launch { BLEHub.susScanDevice() }
    }

    /**
     * 点击设备进行连接
     * @param device BLEDeviceData
     */
    fun onClickDevice(device: BLEDeviceData) {
        UiViewModelManager.showLoading("正在连接...")
        viewModelScope.launch {
            val type = device.type
            // 设置通讯分包大小
            BLEHub.setSplitWriteNum(type?.getSendDataPackageSize()?: 20)
            val isSuccess = BLEHub.connectDevice(device.info, type?.getConnectSetting()?: NotifySettingInfo())
            if (isSuccess.not()) {
                UiViewModelManager.hideLoading()
                UiViewModelManager.showErrorNotify("连接失败！")
                BLEHub.disconnectAll()
                return@launch
            }
            // 连接成功，进行初始化
            UiViewModelManager.showLoading("正在初始化...")
            // 协议重置
            var settingProto = SettingRepository.protoFlow.value
            if (type != null && device.type.getProtoVersion() != settingProto) {
                // 根据设备适配的协议版本设置协议版本
                SettingRepository.setProto(type.getProtoVersion())
                settingProto = type.getProtoVersion()
            }
            Beidou.onDeviceConnected(settingProto)
            type?.onDeviceConnected()
            UiViewModelManager.hideLoading()
            BLEDeviceManager.setConnectedDevice(type)
            back()
        }
    }
}